<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    function MyPromise(excutor) {
      this.PromiseState = 'pending'
      this.PromiseResult = undefined
      this.callbacks = []
      const self = this // 下面两个函数没有调用它的对象，默认this指向为window

      function resolve_(data) {
        if (self.PromiseState !== 'pending') return
          // 1. 修改对象的状态
        self.PromiseState = 'fulfilled'
          // 2. 修改对象的结果值
        self.PromiseResult = data

        // 在这里调用then中的异步回调函数
        self.callbacks.forEach(callback => {
          // 异步回调返回值
          callback.onResolved(self.PromiseResult)
        })
      }

      function reject_(data) {
        if (self.PromiseState !== 'pending') return
          // 1. 修改对象的状态
        self.PromiseState = 'rejected'
          // 2. 修改对象的结果值
        self.PromiseResult = data

        // 在这里调用then中的异步回调函数
        self.callbacks.forEach(callback => {
          callback.onRejected(self.PromiseResult)
        })
      }

      try {
        // 调用执行器函数
        excutor(resolve_, reject_)
      } catch (e) {
        // 修改promise状态为rejected
        reject_(e)
      }
    }

    MyPromise.prototype.then = function(onResolved, onRejected) {
      if (this.PromiseState === 'fulfilled') {
        try {
          // then方法的返回值
          let thenReturn = onResolved(this.PromiseResult)
          if (thenReturn instanceof MyPromise) {
            // 返回值为Mypromise对象
            return thenReturn
          } else {
            // 返回值为非MyPromise对象
            return new MyPromise((resolve, reject) => {
              reject(e)
            })
          }
        } catch (e) {
          return new MyPromise((resolve, reject) => {
            reject(e)
          })
        }
      } else if (this.PromiseState === 'rejected') {
        onRejected(this.PromiseResult)
      } else if (this.PromiseState === 'pending') {
        this.callbacks.push({
          onResolved,
          onRejected
        })
      }
    }

    let m = new MyPromise((resolve, reject) => {
      resolve('resolve')
    })

    m.then(value => {
      console.log(value + '000');

      return new MyPromise((resolve, reject) => {
        resolve('resolveAgain')
      })
    }, (reason) => {
      console.log(reason)
    }).then(res => {
      console.log(res);
    })
  </script>
</body>

</html>